package com.dss.code_generation.util;

import com.dss.code_generation.config.DssProperties;
import com.dss.code_generation.dto.AutoDto;
import com.dss.code_generation.domain.Tables;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * @Description: 图形化工具生成
 * @ClassName: BeanUtils
 * @author: dongshoushan
 * @date: 2020年04月20日 9:13
 */
@Component
@Slf4j
public class AutoCodeUtils {

    @Value("${spring.datasource.druid.url}")
    private String URL;
    @Value("${spring.datasource.druid.username}")
    private String USER;
    @Value("${spring.datasource.druid.password}")
    private String PASSWORD;
    @Value("${spring.datasource.druid.driver-class-name}")
    private String DRIVER;

    @Resource
    private DssProperties dssProperties;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public static final String VO_REQ = "/vo/request/";
    public static final String CONTROLLER = "/controller";
    public static final String DOMAIN = "/domain";
    public static final String DTO = "/dto";
    public static final String SERVICE = "/service";
    public static final String SERVICE_IMPL = "/service/impl";
    public static final String MAPPER = "/mapper";
    public static final String VO = "/vo";
    public static final String CONVERTER = "/utils/converter";

    public String lowerCase(String str) {
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }
    private String getModuleName(AutoDto autoDto) {
        String moduleName = autoDto.getContentPathWeb().substring(autoDto.getContentPathWeb().lastIndexOf("/"));
        return moduleName;
    }


    /**
     * 连接数据库
     *
     * @return
     * @throws Exception
     */
    public Connection getConnection() throws Exception {
        Class.forName(DRIVER);
        Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
        return connection;
    }

    public void generate(AutoDto autoDto, Tables tables) {
        try {
            String module = autoDto.getModule();
            String[] split = module.split(",");
            CountDownLatch mainLatch = new CountDownLatch(split.length);
            for (String s : split) {
                switch (s){
                    case "Entity":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createEntity(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;
                    case "HTML":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createHTML(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "Vo":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createVo(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "AddDto":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createAddDto(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "UpdateDto":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createUpdateDto(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "PageDto":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createPageDto(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "Mapper":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createMapper(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;
                    case "Mapper_xml":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createMapperXml(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;
                    case "Service":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createBeanService(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;
                    case "ServiceImpl":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createBeanServiceImpl(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;
                    case "Controller":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createBeanController(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    case "JunitTest":  threadPoolTaskExecutor.execute(() -> {
                        try {
                            createBeanJunitTest(autoDto,tables);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        mainLatch.countDown();
                    });break;

                    default: mainLatch.countDown(); log.info("未找到代码模块{}的生成方法",s);
                }
            }
            try {
                mainLatch.await();
                log.info("{}的代码自动生成完毕！！",tables.getTableName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void createBeanJunitTest(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String basePath = getTestBasePath(autoDto)+CONTROLLER;
        final String suffix = "ControllerTest.java";
        final String path = basePath+ "/" + getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "test.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","controller");
        //设置支持方法
        setSupportedMethods(autoDto, dataMap);
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    private void createHTML(AutoDto autoDto, Tables tables) throws Exception {
        String pagePath = autoDto.getAbsolutePathWeb() + "/src/main/webapp/page/"+lowerCaseTableName(tables.getTableName())+"/";
        //创建文件夹
        File filePath = new File(pagePath);
        createFilePath(filePath);

        final String path1 = pagePath +  "add.html";
        final String name1 = "addhtml.ftl";
        File file1 = new File(path1);
        log.info("生成文件----->{}",path1);
        Map<String, Object> dataMap = new HashMap<>(16);
        generateFileByTemplate(autoDto,tables,name1, file1, dataMap);

        final String path2 = pagePath +  "add.js";
        final String name2 = "addjs.ftl";
        File file2 = new File(path2);
        log.info("生成文件----->{}",path2);
        generateFileByTemplate(autoDto,tables,name2, file2, dataMap);

        final String path3 = pagePath +  "update.html";
        final String name3 = "updatehtml.ftl";
        File file3 = new File(path3);
        log.info("生成文件----->{}",path3);
        generateFileByTemplate(autoDto,tables,name3, file3, dataMap);

        final String path4 = pagePath +  "update.js";
        final String name4 = "updatejs.ftl";
        File file4 = new File(path4);
        log.info("生成文件----->{}",path4);
        generateFileByTemplate(autoDto,tables,name4, file4, dataMap);

        final String path5 = pagePath +  "list.html";
        final String name5 = "listhtml.ftl";
        File file5 = new File(path5);
        log.info("生成文件----->{}",path5);
        generateFileByTemplate(autoDto,tables,name5, file5, dataMap);

        final String path6 = pagePath +  "list.js";
        final String name6 = "listjs.ftl";
        File file6 = new File(path6);
        log.info("生成文件----->{}",path6);
        generateFileByTemplate(autoDto,tables,name6, file6, dataMap);


    }

    //private void createConverter(AutoDto autoDto, Tables tables) throws Exception {
    //    String tableName = tables.getTableName();
    //    //生成实体类
    //    final String suffix = "Converter.java";
    //    String basePath = getWebBasePath(autoDto)+ CONVERTER +"/";
    //    final String path = basePath +  getSecondUnderLineAndUpperCase(tableName) + suffix;
    //    final String templateName = "converter.ftl";
    //    File mapperFile = new File(path);
    //    //创建文件
    //    File filePath = new File(basePath);
    //    createFilePath(filePath);
    //    log.info("生成文件----->{}",path);
    //
    //    Map<String, Object> dataMap = new HashMap<>(16);
    //    dataMap.put("fileType","vo");
    //    String contentPathWeb = autoDto.getContentPathWeb();
    //    dataMap.put("fileName",getSecondUnderLineAndUpperCase(tableName) + "Vo");
    //    String converterPath = (contentPathWeb.trim()+CONVERTER).replace("/",".").replace("\\",".");
    //    dataMap.put("converterPath", converterPath);
    //    //实体类包路径
    //    String entityPath = (contentPathWeb.trim()+DOMAIN).replace("/",".").replace("\\",".");
    //    dataMap.put("entityPath", entityPath);
    //
    //
    //    generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    //}


    private void createPageDto(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        //生成实体类
        final String suffix = "PageDto.java";
        String basePath = getWebBasePath(autoDto)+ DTO;
        final String path = basePath + "/"+  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "pageDto.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);

        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType",getSecondUnderLineAndUpperCase(tableName)+"PageDto");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    private void createAddDto(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        //生成实体类
        final String suffix = "AddDto.java";
        String basePath = getWebBasePath(autoDto)+ DTO;
        final String path = basePath + "/"+ getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "addDto.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","addDto");
        dataMap.put("fileName",getSecondUnderLineAndUpperCase(tableName)+"AddDto");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }



    private void createUpdateDto(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        //生成实体类
        final String suffix = "UpdateDto.java";
        String basePath = getWebBasePath(autoDto)+ DTO;
        final String path = basePath + "/"+  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "updateDto.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","updateDto");
        dataMap.put("fileName",getSecondUnderLineAndUpperCase(tableName)+"UpdateDto");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    /**
     * 生成Model实体类文件
     */
    public void createEntity(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        //生成实体类
        final String suffix = ".java";
        String basePath = getWebBasePath(autoDto)+ DOMAIN+"/";
        final String path = basePath +  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "entity.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);

        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","entity");
        dataMap.put("fileName",getSecondUnderLineAndUpperCase(tableName));
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    /**
     * 生成Model实体类文件
     */
    public void createVo(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        //生成实体类
        final String suffix = "Vo.java";
        String basePath = getWebBasePath(autoDto)+ VO +"/";
        final String path = basePath +  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "vo.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);

        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","vo");
        dataMap.put("fileName",getSecondUnderLineAndUpperCase(tableName) + "Vo");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    private void createMapperXml(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String modelName = getModuleName(autoDto);
        String resourcesPath = autoDto.getAbsolutePathWeb() + "/src/main/resources/mapper/"+modelName+"/";
        final String suffix = "Mapper.xml";
        final String path = resourcesPath  + getSecondUnderLineAndUpperCase(tableName)  + suffix;
        final String templateName = "mapperXml.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(resourcesPath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        List<ColumnClass> columnList = getColumnList(tableName);
        dataMap.put("columnList", columnList);
        //除了id之外的字段
        List<ColumnClass> columnListNotId = getColumnListNotId(tableName);
        dataMap.put("columnListNotId", columnListNotId);
        String fields = "";
        for (ColumnClass columnClass : columnList) {
            fields += columnClass.getColumnName() +",";
        }
        fields = fields.substring(0,fields.length() - 1);
        dataMap.put("fields",fields);
        dataMap.put("fieldsNotId",fields.substring(3));
        String fieldsNotIdValue = "";
        for (ColumnClass columnClass : columnListNotId) {
            fieldsNotIdValue += "#{"+columnClass.getChangeColumnName()+"},";
        }
        dataMap.put("fieldsNotIdValue",fieldsNotIdValue.substring(0,fieldsNotIdValue.length() - 1));
        String fieldsNotIdValueItem = "";
        for (ColumnClass columnClass : columnListNotId) {
            fieldsNotIdValueItem += "#{item."+columnClass.getChangeColumnName()+"},";
        }
        dataMap.put("fieldsNotIdValueItem",fieldsNotIdValueItem.substring(0,fieldsNotIdValueItem.length() - 1));
        dataMap.put("fileType","xml");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }



    /**
     * 生成serviceImpl
     *
     * @param
     */
    private void createBeanServiceImpl(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String basePath = getWebBasePath(autoDto)+SERVICE_IMPL;
        final String suffix = "ServiceImpl.java";
        final String path = basePath +"/" +  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "serviceImpl.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","impl");
        String contentPathWeb = autoDto.getContentPathWeb();
        String converterPath = (contentPathWeb.trim()+CONVERTER).replace("/",".").replace("\\",".");
        dataMap.put("converterPath", converterPath);
        //设置支持方法
        setSupportedMethods(autoDto, dataMap);
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    /**
     * 生成控制层
     *
     * @param
     */
    private void createBeanController(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String basePath = getWebBasePath(autoDto)+CONTROLLER;
        final String suffix = "Controller.java";
        final String path = basePath+ "/" + getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "controller.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","controller");
        //设置支持方法
        setSupportedMethods(autoDto, dataMap);
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    /**
     * 设置支持方法
     *
     * @param autoDto 自动dto
     * @param dataMap 数据图
     */
    private static void setSupportedMethods(AutoDto autoDto, Map<String, Object> dataMap) {
        List<String> methodList = Arrays.asList(autoDto.getMethod().split(","));
        dataMap.put("add",methodList.contains("add"));
        dataMap.put("update",methodList.contains("update"));
        dataMap.put("delete",methodList.contains("delete"));
        dataMap.put("page",methodList.contains("page"));
        dataMap.put("getVoById",methodList.contains("getVoById"));
        dataMap.put("getAll",methodList.contains("getAll"));
    }


    /**
     * 生成service
     *
     * @param
     */
    private void createBeanService(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String basePath = getWebBasePath(autoDto)+SERVICE;
        final String suffix = "Service.java";
        final String path = basePath +"/I" +  getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "service.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath );
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","service");
        //设置支持方法
        setSupportedMethods(autoDto, dataMap);
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }


    /**
     * 生成Mapper文件
     *
     * @param
     */
    private void createMapper(AutoDto autoDto, Tables tables) throws Exception {
        String tableName = tables.getTableName();
        String basePath = getWebBasePath(autoDto);
        final String suffix = "Mapper.java";
        basePath  = basePath + MAPPER;
        final String path = basePath + "/"+ getSecondUnderLineAndUpperCase(tableName) + suffix;
        final String templateName = "mapper.ftl";
        File mapperFile = new File(path);
        //创建文件
        File filePath = new File(basePath);
        createFilePath(filePath);
        log.info("生成文件----->{}",path);
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("fileType","mapper");
        generateFileByTemplate(autoDto,tables,templateName, mapperFile, dataMap);
    }

    private void generateFileByTemplate(AutoDto autoDto, Tables tables, final String templateName, File file, Map<String, Object> dataMap) throws Exception {
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);

        String tableName = tables.getTableName();
        //所有字段
        List<ColumnClass> columnList = getColumnList(tableName);
        dataMap.put("columnList", columnList);
        List<String> columnNameList = columnList.stream().map(ColumnClass::getChangeColumnName).collect(Collectors.toList());
        dataMap.put("createBy",columnNameList.contains("createBy"));
        dataMap.put("updateBy",columnNameList.contains("updateBy"));
        dataMap.put("createTime",columnNameList.contains("createTime"));
        dataMap.put("updateTime",columnNameList.contains("updateTime"));
        dataMap.put("isDeleted",columnNameList.contains("isDeleted"));
        //所有字段,除了删除字段is_deleted
        List<ColumnClass> columnListNotStatus = getColumnListNotStatus(tableName);
        dataMap.put("columnListNotStatus", columnListNotStatus);
        //除了id之外的字段
        List<ColumnClass> columnListNotId = getColumnListNotId(tableName);
        dataMap.put("columnListNotId", columnListNotId);
        //除了id和时间创建人之外的字段
        List<ColumnClass> columnListNotIdAndTimeAndUser = getColumnListNotIdAndTimeAndUser(tableName);
        dataMap.put("columnListNotIdAndTimeAndUser", columnListNotIdAndTimeAndUser);
        //除了时间之外的字段
        List<ColumnClass> columnListNotTimeAndUser = getColumnListNotTimeAndUser(tableName);
        dataMap.put("columnListNotTimeAndUser", columnListNotTimeAndUser);

        //表名
        dataMap.put("tableName", tables.getTableName());
        //实体类大写
        dataMap.put("EntityName", getSecondUnderLineAndUpperCase(tables.getTableName()));
        //实体类前缀小写
        dataMap.put("lowName", lowerCaseTableName(tables.getTableName()));
        dataMap.put("author", autoDto.getAuthor());
        dataMap.put("date", getDate());
        dataMap.put("table_annotation", tables.getTableComment());
        String contentPathWeb = autoDto.getContentPathWeb();
        //实体类包路径
        String entityPath = (contentPathWeb.trim()+DOMAIN).replace("/",".").replace("\\",".");
        dataMap.put("entityPath", entityPath);
        //vo路径
        String voPath = (contentPathWeb.trim()+ VO).replace("/",".").replace("\\",".");
        dataMap.put("voPath", voPath);
        //vo路径
        String dtoPath = (contentPathWeb.trim()+DTO).replace("/",".").replace("\\",".");
        dataMap.put("dtoPath", dtoPath);
        String servicePath = (contentPathWeb.trim()+SERVICE).replace("/",".").replace("\\",".");
        dataMap.put("servicePath",servicePath);
        String serviceImplPath = (contentPathWeb.trim()+SERVICE_IMPL).replace("/",".").replace("\\",".");
        dataMap.put("serviceImplPath",serviceImplPath);
        String mapperPath = (contentPathWeb.trim()+MAPPER).replace("/",".").replace("\\",".");
        dataMap.put("mapperPath",mapperPath);
        String controllerPath = (contentPathWeb.trim()+CONTROLLER).replace("/",".").replace("\\",".");
        dataMap.put("controllerPath",controllerPath);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8), 10240);
        template.process(dataMap, out);
        fos.close();
        out.close();
    }

    private String getToString(String fileName, List<ColumnClass> columnList) {
        StringBuilder sb = new StringBuilder("\"");
        sb.append(fileName).append("{\"").append("+").append(System.getProperty("line.separator"));
        ColumnClass columnClass1 = columnList.get(0);
        String name1 = columnClass1.getChangeColumnName();
        sb.append("                ").append("\"").append(name1).append("=").append("\"").append("+")
                .append(name1).append("+").append(System.getProperty("line.separator"));
        for (int i = 1; i < columnList.size(); i++) {
            ColumnClass columnClass = columnList.get(i);
            String changeColumnName = columnClass.getChangeColumnName();
            sb.append("                ").append("\",").append(changeColumnName).append("=").append("\"").append("+")
                    .append(changeColumnName).append("+").append(System.getProperty("line.separator"));
        }
        sb.append("                ").append("\'}'");
        return sb.toString();
    }

    public List<ColumnClass> getColumnList(String tableName) throws Exception {
        Connection connection = getConnection();
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        ResultSet resultSet = databaseMetaData.getColumns(connection.getCatalog(), "%", tableName, "%");
        List<ColumnClass> columnClassList = new ArrayList<>();
        ColumnClass columnClass;
        while (resultSet.next()) {
            columnClass = new ColumnClass();
            //获取字段名称
            columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
            //获取字段类型
            columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
            //转换字段名称，如 sys_name 变成 SysName
            columnClass.setUpColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
            columnClass.setChangeColumnName(lowerCase(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME"))));
            //设置java类型
            columnClass.setJavaType(setEntityJavaType(resultSet.getString("TYPE_NAME")));
            //字段在数据库的注释
            columnClass.setColumnComment(resultSet.getString("REMARKS")==null?"":resultSet.getString("REMARKS"));
            //设置yapi里面的类型
            columnClass.setYapiType(setYapiType(columnClass.getJavaType()));
            columnClass.setColumnSize(resultSet.getInt("COLUMN_SIZE"));
            int isNullable = resultSet.getInt("NULLABLE");
            columnClass.setRequired((isNullable == ResultSetMetaData.columnNoNulls));
            columnClass.setColumnDefault(resultSet.getString("COLUMN_DEF"));
            columnClassList.add(columnClass);
        }
        connection.close();
        return columnClassList;
    }

    private String setYapiType(String javaType) {
        if ("Integer".equals(javaType) || "Long".equals(javaType) ) {
            return "integer";
        }else {
            return "string";
        }
    }

    /**
     * 除了id之外的字段
     * @param tableName
     * @return
     * @throws SQLException
     */
    private List<ColumnClass> getColumnListNotId(String tableName) throws Exception {
        List<ColumnClass> columnList = getColumnList(tableName);
        columnList.removeIf(c->c.getColumnName().equals("id"));
        return columnList;
    }
    /**
     * 除了id之外的字段
     * @param tableName
     * @return
     * @throws SQLException
     */
    private List<ColumnClass> getColumnListNotStatus(String tableName) throws Exception {
        List<ColumnClass> columnList = getColumnList(tableName);
        columnList.removeIf(c->c.getColumnName().equals("is_deleted"));
        return columnList;
    }
    /**
     * 除了id之外的字段
     * @param tableName
     * @return
     * @throws SQLException
     */
    private List<ColumnClass> getColumnListNotTimeAndUser(String tableName) throws Exception {
        List<ColumnClass> columnList = getColumnList(tableName);
        columnList.removeIf(c->c.getColumnName().equals("create_time"));
        columnList.removeIf(c->c.getColumnName().equals("update_time"));
        columnList.removeIf(c->c.getColumnName().equals("create_by"));
        columnList.removeIf(c->c.getColumnName().equals("update_by"));
        columnList.removeIf(c->c.getColumnName().equals("is_deleted"));
        return columnList;
    }
    /**
     * 除了id，时间之外的字段
     * @param tableName
     * @return
     * @throws SQLException
     */
    private List<ColumnClass> getColumnListNotIdAndTime(String tableName) throws Exception {
        List<ColumnClass> columnList = getColumnList(tableName);
        columnList.removeIf(c->c.getColumnName().equals("id"));
        columnList.removeIf(c->c.getColumnName().equals("create_time"));
        columnList.removeIf(c->c.getColumnName().equals("update_time"));
        return columnList;
    }
    /**
     * 除了id，时间之外的字段
     * @param tableName
     * @return
     * @throws SQLException
     */
    private List<ColumnClass> getColumnListNotIdAndTimeAndUser(String tableName) throws Exception {
        List<ColumnClass> columnList = getColumnList(tableName);
        columnList.removeIf(c->c.getColumnName().equals("id"));
        columnList.removeIf(c->c.getColumnName().equals("create_time"));
        columnList.removeIf(c->c.getColumnName().equals("update_time"));
        columnList.removeIf(c->c.getColumnName().equals("create_by"));
        columnList.removeIf(c->c.getColumnName().equals("update_by"));
        columnList.removeIf(c->c.getColumnName().equals("is_deleted"));
        return columnList;
    }


    private String getWebBasePath(AutoDto autoDto) {
        String basePath = autoDto.getAbsolutePathWeb()+  "/src/main/java/" + autoDto.getContentPathWeb();
        return basePath;
    }
    private String getTestBasePath(AutoDto autoDto) {
        String basePath = autoDto.getAbsolutePathWeb()+  "/src/test/java/" + autoDto.getContentPathWeb();
        return basePath;
    }
    /**
     * 获取系统时间
     *
     * @return
     */
    public static String getDate() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        return simpleDateFormat.format(date);
    }

    /**
     * 实体类首字母小写
     * @param str
     * @return
     */
    public String lowerCaseTableName(String str) {
        str = getSecondUnderLineAndUpperCase(str);
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    /**
     * 表名字转实体类
     * @param str
     * @return
     */
    public  String getSecondUnderLineAndUpperCase(String str) {
        String[] ignorePrefix = dssProperties.getIgnorePrefix();
        List<String> strings = Arrays.asList(ignorePrefix);
        for (String s : strings) {
            if (str.startsWith(s)) {
                str = str.replace(s,"");
            }
        }
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while (count != 0) {
            int num = sb.indexOf("_", count);
            count = num + 1;
            if (num != -1) {
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count, count + 1, ia + "");
            }
        }
        String result = sb.toString().replaceAll("_", "");
        return StringUtils.capitalize(result);
    }

    public static String replaceUnderLineAndUpperCase(String str) {
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while (count != 0) {
            int num = sb.indexOf("_", count);
            count = num + 1;
            if (num != -1) {
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count, count + 1, ia + "");
            }
        }
        String result = sb.toString().replaceAll("_", "");
        return StringUtils.capitalize(result);
    }

    /**
     * 创建文件
     *
     * @param file
     */
    public void createFilePath(File file) {
        if (!file.exists()) {
            log.info("创建[{}]情况：{}" ,file.getAbsolutePath(), file.mkdirs());
        } else {
            log.info("存在目录：{}" , file.getAbsolutePath());
        }
    }
    private String setEntityJavaType(String typeName) {
        String javaType;
        typeName = typeName.toUpperCase();
        switch (typeName) {
            case "BIGINT":
                javaType = "Long";
                break;
            case "BIGSERIAL":
                javaType = "Long";
                break;
            case "INT8":
                javaType = "Long";
                break;
            case "VARCHAR":
                javaType = "String";
                break;
            case "VARBINARY":
                javaType = "String";
                break;
            case "SERIAL":
                javaType = "Integer";
                break;
            case "INT":
                javaType = "Integer";
                break;
            case "INT4":
                javaType = "Integer";
                break;
            case "TINYINT":
                javaType = "Integer";
                break;
            case "SMALLINT":
                javaType = "Integer";
                break;
            case "FLOAT":
                javaType = "Float";
                break;
            case "DOUBLE":
                javaType = "Double";
                break;
            case "DATE":
                javaType = "Date";
                break;
            case "TIME":
                javaType = "Date";
                break;
            case "TIMESTAMP":
                javaType = "Date";
                break;
            case "TEXT":
                javaType = "String";
                break;
            case "DECIMAL":
                javaType = "BigDecimal";
                break;
            case "DATETIME":
                javaType = "Date";
                break;
            case "CHAR":
                javaType = "String";
                break;
            case "BOOL":
                javaType = "Boolean";
                break;
            default:
                javaType = "String";
        }
        return javaType;
    }

}
